package com.legal.config;

import com.legal.domain.result.RestfulAccessDeniedHandler;
import com.legal.domain.result.RestfulAuthenticationEntryPoint;
import com.legal.filter.JwtAuthenticationTokenFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


// 配置类，用于配置Spring Security
@Configuration
@EnableWebSecurity // 启用Spring Security
@EnableMethodSecurity // 如果需要方法级安全控制
@RequiredArgsConstructor
public class SecurityConfig {

    //    private final CustomUrlDecisionManager customUrlDecisionManager;
//    private final CustomFilter customFilter;
    private final RestfulAccessDeniedHandler restfulAccessDeniedHandler;
    private final RestfulAuthenticationEntryPoint restfulAuthenticationEntryPoint;
//    private final JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // 禁用CSRF和Session
                .csrf(AbstractHttpConfigurer::disable) // 关闭 CSRF（如果是 API 服务）
                .sessionManagement(session -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )

                .authorizeHttpRequests(auth -> auth
                        /*
                        permitAll 和 authenticated 核心区别对比表：
                               特性	.permitAll()	.authenticated()
                               认证要求	完全不需要认证	必须携带有效认证信息（如 JWT）
                               权限检查	跳过所有权限检查	仍会执行权限检查（如 @PreAuthorize）
                               过滤器执行	仍然会经过所有过滤器	必须通过过滤器认证
                               适用场景	登录接口/公开资源	需要登录但无需特定角色的接口
                               安全性	低（完全开放）	中（需认证但不限角色）
                         */
                        // permitAll(): 确保这些路径不需要任何权限即可访问（跳过 AuthorizationManager 检查）。
                        .requestMatchers("/user/login").permitAll() // 登录接口，跳过所有权限检查,仍然会经过所有过滤器
                        .requestMatchers("/user/register").permitAll() // 注册接口
                        .requestMatchers("/captcha/**").permitAll() // 验证码接口
                        .requestMatchers("/wxCheck").permitAll() // 微信验证
                        .requestMatchers("/wx/**").permitAll() // 微信登录
                        .requestMatchers(
                                "/swagger-ui/**",
                                "/v3/api-docs/**",
                                "/webjars/**",
                                "/swagger-resources/**",
                                "/doc.html",
                                "/favicon.ico"
                        ).permitAll() // 放行 Swagger
                        .requestMatchers("/ai/chat/stream").permitAll() // 跳过所有权限检查,仍然会经过所有过滤器
                        .requestMatchers("/ai/analysis/chat").permitAll() // 跳过所有权限检查,仍然会经过所有过滤器
                        .requestMatchers("/ai/media/test").permitAll() // 跳过所有权限检查,仍然会经过所有过滤器
                        //.requestMatchers("/ai/chat/stream").authenticated() // 需要身份认证

                        /* 关于接口/ai/chat/stream的访问权限问题：
                            流式接口 /ai/chat/stream 必须使用 .permitAll() 才能工作，用 .authenticated() 会报错，
                            这通常是由流式响应特性与 Spring Security 的交互方式冲突导致的。

                            1.响应立即提交：Flux<String> 会立即开始发送数据，导致响应头被提前提交
                            2.权限检查滞后：Spring Security 的 @PreAuthorize 和 .authenticated() 在控制器方法执行时检查权限，此时响应已开始
                         */

                        .anyRequest().authenticated() // 其他所有接口需要身份认证
                )


                // 自定义权限配置
//                .with(configureCustomSecurity -> {
//                    FilterSecurityInterceptor securityInterceptor = new FilterSecurityInterceptor();
//                    securityInterceptor.setAccessDecisionManager(customUrlDecisionManager);
//                    securityInterceptor.setSecurityMetadataSource(customFilter);
//                    configureCustomSecurity.add(securityInterceptor);
//                })

                // 禁用缓存 可以防止某些安全漏洞，如 CSRF 攻击。
                .headers(headers -> headers
                        .cacheControl(HeadersConfigurer.CacheControlConfig::disable)
                )

                // 添加 自定义的 JWT 过滤器
                // JwtAuthenticationTokenFilter 是通过
                // .addFilterBefore() 手动添加的，属于过滤器链的一部分，所有请求都会经过它。
                .addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);

//                // 异常处理
//                .exceptionHandling(exception -> exception
//                        .accessDeniedHandler(restfulAccessDeniedHandler)
//                        .authenticationEntryPoint(restfulAuthenticationEntryPoint)
//                );

        return http.build();
    }


    /**
     * 配置并返回一个密码编码器实例
     * 作用：
     * 1. 对用户密码进行安全存储的加密处理（BCrypt算法）
     * 2. 在用户登录时对输入密码进行匹配验证
     * 3. 提供工业级安全的密码存储方案，自动处理盐值(salt)生成和存储
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 使用 BCrypt 强哈希算法实现安全的密码编码
        // strength 参数默认为 10，表示加密强度（工作因子）
        return new BCryptPasswordEncoder();
    }


    /**
     * 配置 AuthenticationManager Bean
     * 作用：
     * 1. 提供认证管理器用于处理登录认证请求
     * 2. 通过 AuthenticationConfiguration 获取认证管理器实例
     * 3. 在 Spring Security 框架中，AuthenticationManager 是核心接口，
     * 负责处理所有的认证请求（如用户名密码登录、JWT令牌验证等）
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
        return authConfig.getAuthenticationManager();
    }

    /**
     * 创建 JwtAuthenticationTokenFilter Bean
     * 作用：
     * 1. 将 JWT 认证过滤器注册为 Spring 容器中的 Bean
     * 2. 用于在安全过滤器链中拦截请求并验证 JWT 令牌的有效性
     * 3. 在认证流程中解析用户身份信息，并将其封装成 Authentication 对象供后续处理使用
     *
     * @return 配置好的 JwtAuthenticationTokenFilter 实例
     */
    @Bean
    public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
        return new JwtAuthenticationTokenFilter();
    }

}
